#!/bin/bash

# Copyright 2015--2019 Jan Pazdziora
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Initialization of /data (bind-mounted volume) from /data-template
# we IPA server was not yet configured.

set -e

# Turn on tracing of this script
test -z "$DEBUG_TRACE" || {
	set -x
	if [ "${DEBUG_TRACE}" == "2" ]; then
		export SYSTEMD_LOG_LEVEL="debug"
		export SYSTEMD_LOG_TARGET="journal+console"
		export SYSTEMD_LOG_COLOR="no"
		export DEBUG=1
	fi
}

cd /

case "$1" in
	/bin/install.sh|/bin/uninstall.sh|/bin/bash|bash)
		exec "$@"
	;;
esac

for i in /run/* /tmp/var/tmp/* /tmp/* ; do
	if [ "$i" == '/run/secrets' ] ; then
		:
	elif [ -L "$i" -o -f "$i" ] ; then
		rm -f "$i"
	else
		for j in "$i"/* ; do
			if [ "$j" != '/tmp/var/tmp' ] ; then
				rm -rf "$j"
			fi
		done
	fi
done

/usr/local/bin/populate-volume-from-template /tmp

# Workaround 1373562
mkdir -p /run/lock

DATA=/data
DATA_TEMPLATE=/data-template

mkdir -p /run/ipa /run/log $DATA/var/log/journal
ln -s $DATA/var/log/journal /run/log/journal

if [ "$1" == 'no-exit' -o -n "$DEBUG_NO_EXIT" ] ; then
	if [ "$1" == 'no-exit' ] ; then
		shift
	fi
	# Debugging:  Don't power off if IPA install/upgrade fails
	# Create service drop-in to override `FailureAction`
	for i in ipa-server-configure-first.service ipa-server-upgrade.service; do
		mkdir -p /run/systemd/system/$i.d
		echo -e "[Service]\nFailureAction=none" > /run/systemd/system/$i.d/50-no-poweroff.conf
	done
elif [ "$1" == 'exit-on-finished' ] ; then
	for i in ipa-server-configure-first.service ipa-server-upgrade.service; do
		mkdir -p /run/systemd/system/$i.d
		# We'd like to use SuccessAction=poweroff here but it's only
		# available in systemd 236.
		echo -e "[Service]\nExecStartPost=/usr/bin/systemctl poweroff" > /run/systemd/system/$i.d/50-success-poweroff.conf
	done
	shift
fi

# Debugging:  Turn on tracing of ipa-server-configure-first script
test -z "$DEBUG_TRACE" || touch /run/ipa/debug-trace

COMMAND=
if [ -n "$1" ] ; then
	case "$1" in
		ipa-server-install)
			COMMAND="$1"
			shift
		;;
		ipa-replica-install)
			COMMAND="$1"
			shift
		;;
		-*)
			:
		;;
		*)
		echo "Invocation error: command [$1] not supported." >&2
		exit 8

	esac
fi
if [ -z "$COMMAND" ] ; then
	if [ -f $DATA/ipa-replica-install-options ] ; then
		COMMAND=ipa-replica-install
	else
		COMMAND=ipa-server-install
	fi
fi

if [ -n "$IPA_SERVER_INSTALL_OPTS" -a "$COMMAND" != 'ipa-server-install' -a "$COMMAND" != 'ipa-replica-install' ] ; then
	echo "Invocation error: IPA_SERVER_INSTALL_OPTS should only be used with ipa-server-install or ipa-replica-install." >&2
	exit 7
fi

OPTIONS_FILE=/run/ipa/$COMMAND-options

DATA_OPTIONS_FILE=$DATA/$COMMAND-options
touch $OPTIONS_FILE
chmod 660 $OPTIONS_FILE
for i in "$@" ; do
	printf '%q\n' "$i" >> $OPTIONS_FILE
done

_HOSTNAME_IN_NEXT=false
for i in $( cat $OPTIONS_FILE ) ; do
	if $_HOSTNAME_IN_NEXT ; then
		IPA_SERVER_HOSTNAME="$i"
		break
	fi
        case "$i" in
                "--hostname" | "-h")
			_HOSTNAME_IN_NEXT=true
                        ;;
                --hostname=*)
                        IPA_SERVER_HOSTNAME="${i#--hostname=}"
                        break
                        ;;
	esac
done

if [ -f "$DATA/hostname" ] ; then
	STORED_HOSTNAME="$( cat $DATA/hostname )"
	if ! [ "$HOSTNAME" == "$STORED_HOSTNAME" ] ; then
		# Attempt to set hostname from within container, this
		# will pass if the container has SYS_ADMIN capability.
		if hostname $STORED_HOSTNAME 2> /dev/null ; then
			HOSTNAME=$( hostname )
			if [ "$HOSTNAME" == "$STORED_HOSTNAME" ] && ! [ "$IPA_SERVER_HOSTNAME" == "$HOSTNAME" ] ; then
				echo "Using stored hostname $STORED_HOSTNAME, ignoring $IPA_SERVER_HOSTNAME."
			fi
		fi
	fi
	IPA_SERVER_HOSTNAME=$STORED_HOSTNAME
fi

HOSTNAME_SHORT=${HOSTNAME%%.*}
if [ "$HOSTNAME_SHORT" == "$HOSTNAME" ] ; then
	if [ -z "$IPA_SERVER_HOSTNAME" ] ; then
		echo "Container invoked without fully-qualified hostname" >&2
		echo "   and without specifying hostname to use." >&2
		echo "Consider using -h FQDN option to docker run." >&2
		exit 15
	fi
	# Container is run without FQDN set, we try to "set" it in /etc/hosts
	cp /etc/hosts /etc/hosts.dist
	sed "s/$HOSTNAME/$IPA_SERVER_HOSTNAME $IPA_SERVER_HOSTNAME. &/" /etc/hosts.dist > /etc/hosts
	rm -f /etc/hosts.dist
	HOSTNAME=$IPA_SERVER_HOSTNAME
fi

if ! [ -f "$DATA/hostname" ] ; then
	echo "$HOSTNAME" > "$DATA/hostname"
fi

function create_machine_id () {
	# only triggers when /etc/machine-id is a symlink and not bind-mounted into
	# the container by a container runtime.
	if [ -L /etc/machine-id ] && [ ! -f $DATA/etc/machine-id ] ; then
		# https://systemd.io/CONTAINER_INTERFACE/
		# shellcheck disable=SC2154
		if [ "${container_uuid}" != "" ]; then
			echo "${container_uuid}" > "${DATA}/etc/machine-id"
		else
			dbus-uuidgen --ensure=$DATA/etc/machine-id
		fi
		chmod 444 $DATA/etc/machine-id
	fi
}

if ! [ -f /etc/ipa/ca.crt ] ; then
	if ! [ -f $DATA/ipa.csr ] ; then
		# Do not refresh $DATA in the second stage of the external CA setup
		/usr/local/bin/populate-volume-from-template $DATA
		create_machine_id
	fi
	if [ -n "$PASSWORD" ] ; then
		if [ "$COMMAND" == 'ipa-server-install' ] ; then
			printf '%q\n' "--admin-password=$PASSWORD" >> $OPTIONS_FILE
			if ! grep -sq '^--ds-password' $OPTIONS_FILE $DATA_OPTIONS_FILE ; then
				printf '%q\n' "--ds-password=$PASSWORD" >> $OPTIONS_FILE
			fi
		elif [ "$COMMAND" == 'ipa-replica-install' ] ; then
			if grep -sq '^--principal' $OPTIONS_FILE $DATA_OPTIONS_FILE ; then
				printf '%q\n' "--admin-password=$PASSWORD" >> $OPTIONS_FILE
			else
				printf '%q\n' "--password=$PASSWORD" >> $OPTIONS_FILE
			fi
		else
			echo "Warning: ignoring environment variable PASSWORD." >&2
		fi
	fi
	if [ -n "$IPA_SERVER_INSTALL_OPTS" ] ; then
		if [ "$COMMAND" == 'ipa-server-install' -o "$COMMAND" = 'ipa-replica-install' ] ; then
			echo "$IPA_SERVER_INSTALL_OPTS" >> $OPTIONS_FILE
		else
			echo "Warning: ignoring environment variable IPA_SERVER_INSTALL_OPTS." >&2
		fi
	fi
	if [ -n "$DEBUG" ] ; then
		echo "--debug" >> $OPTIONS_FILE
	fi
fi

# Check the volume-version of the bind-mounted volume, upgrade if it's
# different from the one in this image.
# The volume-upgrade file names are in format:
#         ipa-volume-upgrade-$OLDVERSION-$NEWVERSION
if [ -f "$DATA/volume-version" ] ; then
	DATA_VERSION=$(cat $DATA/volume-version)
	IMAGE_VERSION=$(cat /etc/volume-version)
	if ! [ "$DATA_VERSION" == "$IMAGE_VERSION" ] ; then
		if [ -x /usr/sbin/ipa-volume-upgrade-$DATA_VERSION-$IMAGE_VERSION ] ; then
			echo "Migrating $DATA data volume version $DATA_VERSION to $IMAGE_VERSION."
			if /usr/sbin/ipa-volume-upgrade-$DATA_VERSION-$IMAGE_VERSION ; then
				cat /etc/volume-version > $DATA/volume-version
			else
				echo "Migration of $DATA volume to version $IMAGE_VERSION failed."
				exit 13
			fi
		fi
	fi
fi
if [ -f "$DATA/build-id" ] ; then
	if ! cmp -s $DATA/build-id $DATA_TEMPLATE/build-id ; then
		echo "FreeIPA server is already configured but with different version, volume update."
		/usr/local/bin/populate-volume-from-template $DATA
		create_machine_id
		sha256sum -c /etc/volume-data-autoupdate 2> /dev/null | awk -F': ' '/OK$/ { print $1 }' \
			| while read f ; do
				rm -f "$DATA/$f"
				if [ -e "$DATA_TEMPLATE/$f" ] ; then
					( cd $DATA_TEMPLATE && tar cf - "./$f" ) | ( cd $DATA && tar xvf - )
				fi
			done
		cat /etc/volume-data-list | while read i ; do
			if [ -e $DATA_TEMPLATE$i -a -e $DATA$i ] ; then
				chown --reference=$DATA_TEMPLATE$i $DATA$i
				chmod --reference=$DATA_TEMPLATE$i $DATA$i
			fi
		done
		SYSTEMD_OPTS=--unit=ipa-server-upgrade.service
	fi
	if [ -f /etc/ipa/ca.crt ] ; then
		rm -f "$DATA/etc/systemd/system/multi-user.target.wants/ipa-server-configure-first.service"
	fi
fi

echo "$(date) $0 $*" >> /var/log/ipa-server-configure-first.log

SHOW_LOG=${SHOW_LOG:-1}
if [ $SHOW_LOG == 1 ] ; then
	for i in /var/log/ipa-server-configure-first.log /var/log/ipa-server-run.log ; do
		if ! [ -f $i ] ; then
			touch $i
		fi
	done
	(
	trap '' SIGHUP
	tail --silent -n 0 -f --retry /var/log/ipa-server-configure-first.log /var/log/ipa-server-run.log 2> /dev/null < /dev/null &
	)
fi

if [ -n "$IPA_SERVER_IP" ] ; then
	echo "$IPA_SERVER_IP" > /run/ipa/ipa-server-ip
fi

[ "$DEBUG_TRACE" != "" ] && env
# exec /usr/sbin/init --show-status=false $SYSTEMD_OPTS
exec /usr/sbin/init --show-status=true $SYSTEMD_OPTS

exit 10
